{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Teleportation Kata\n",
    "\n",
    "**Teleportation** quantum kata is a series of exercises designed to get you familiar with programming in Q#. It covers the quantum teleportation protocol which allows you to communicate a quantum state using only classical communication and previously shared quantum entanglement.\n",
    "\n",
    " - Teleportation is described as an example in [the Q# documentation](https://docs.microsoft.com/quantum/techniques/putting-it-all-together).\n",
    " - Another description can be found in [the Wikipedia article](https://en.wikipedia.org/wiki/Quantum_teleportation).\n",
    " - An interactive demonstration can be found [on the Wolfram Demonstrations Project](http://demonstrations.wolfram.com/QuantumTeleportation/).\n",
    "\n",
    "Each task is wrapped in one operation preceded by the description of the task.  Your goal is to fill in the blank (marked with `// ...` comment) with some Q# code that solves the task. To verify your answer, run the cell using Ctrl/⌘+Enter."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To begin, first prepare this notebook for execution (if you skip this step, you'll get \"Syntax does not match any known patterns\" error when you try to execute Q# code in the next cells):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%package Microsoft.Quantum.Katas::0.10.1911.1607"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> The package versions in the output of the cell above should always match. If you are running the Notebooks locally and the versions do not match, please install the IQ# version that matches the version of the `Microsoft.Quantum.Katas` package.\n",
    "> <details>\n",
    "> <summary><u>How to install the right IQ# version</u></summary>\n",
    "> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.1.2.3, the installation steps are as follows:\n",
    ">\n",
    "> 1. Stop the kernel.\n",
    "> 2. Uninstall the existing version of IQ#:\n",
    ">        dotnet tool uninstall microsoft.quantum.iqsharp -g\n",
    "> 3. Install the matching version:\n",
    ">        dotnet tool install microsoft.quantum.iqsharp -g --version 0.1.2.3\n",
    "> 4. Reinstall the kernel:\n",
    ">        dotnet iqsharp install\n",
    "> 5. Restart the Notebook.\n",
    "> </details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Part I. Standard Teleportation\n",
    "We split the teleportation protocol into several steps, following the description in the [Q# documentation](https://docs.microsoft.com/en-us/quantum/techniques/putting-it-all-together) :\n",
    "    \n",
    "* Preparation (creating the entangled pair of qubits that are sent to Alice and Bob).\n",
    "* Sending the message (Alice's task): Entangling the message qubit with Alice's qubit and extracting two classical bits to be sent to Bob.\n",
    "* Reconstructing the message (Bob's task): Using the two classical bits Bob received from Alice to get Bob's qubit into the state in which the message qubit had been originally.  Finally, we compose these steps into the complete teleportation protocol."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 1.1. Entangled pair\n",
    "\n",
    "**Input:** two qubits qAlice and qBob, each in $|0\\rangle$ state.\n",
    "\n",
    "**Goal:**  prepare a Bell state $|\\Phi^{+}\\rangle = \\frac{1}{\\sqrt{2}}(|00\\rangle + |11\\rangle)$ on these qubits.\n",
    "\n",
    "> In the context of the quantum teleportation protocol, this is the preparation step: qubits qAlice and qBob will be sent to Alice and Bob, respectively."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T11_Entangle_Test \n",
    "\n",
    "operation Entangle (qAlice : Qubit, qBob : Qubit) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 1.2. Send the message (Alice's task)\n",
    "\n",
    "Entangle the message qubit with Alice's qubit and extract two classical bits to be sent to Bob.\n",
    "\n",
    "**Inputs**: \n",
    "1. Alice's part of the entangled pair of qubits qAlice.\n",
    "2. The message qubit qMessage.\n",
    "\n",
    "**Output**:\n",
    "Two classical bits Alice will send to Bob via classical channel as a tuple of Bool values. The first bit in the tuple should hold the result of measurement of the message qubit, the second bit - the result of measurement of Alice's qubit.\n",
    "Represent measurement result 'One' as `true` and 'Zero' as `false`.  The state of the qubits in the end of the operation doesn't matter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T12_SendMessage_Test \n",
    "\n",
    "operation SendMessage (qAlice : Qubit, qMessage : Qubit) : (Bool, Bool) {\n",
    "    // ...\n",
    "    return (false, false);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 1.3. Reconstruct the message (Bob's task)\n",
    "\n",
    "Transform Bob's qubit into the required state using the two classical bits received from Alice.\n",
    "\n",
    "**Inputs**: \n",
    "1. Bob's part of the entangled pair of qubits qBob.\n",
    "2. The tuple of classical bits received from Alice, in the format used in task 1.2.\n",
    "\n",
    "**Goal** : Transform Bob's qubit qBob into the state in which the message qubit had been originally."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T13_ReconstructMessage_Test \n",
    "\n",
    "operation ReconstructMessage (qBob : Qubit, (b1 : Bool, b2 : Bool)) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 1.4. Standard teleportation protocol\n",
    "\n",
    "Put together the steps implemented in tasks 1.1 - 1.3 to implement the full teleportation protocol.\n",
    "\n",
    "**Inputs:**\n",
    "\n",
    "1. The two qubits qAlice and qBob in $|0\\rangle$ state.\n",
    "2. The message qubit qMessage in the state $|\\psi\\rangle$ to be teleported.\n",
    "\n",
    "**Goal:** Transform Bob's qubit qBob into the state $|\\psi\\rangle$. The state of the qubits qAlice and qMessage in the end of the operation doesn't matter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T14_StandardTeleport_Test\n",
    "\n",
    "operation StandardTeleport (qAlice : Qubit, qBob : Qubit, qMessage : Qubit) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 1.5. Prepare a state and send it as a message (Alice's task)\n",
    "\n",
    "Given a Pauli basis along with a state `true` as 'One' or `false` as 'Zero', prepare a message qubit, entangle it with Alice's qubit, and extract two classical bits to be sent to Bob.\n",
    "\n",
    "**Inputs:** \n",
    "\n",
    "1. Alice's part of the entangled pair of qubits qAlice.\n",
    "2. A PauliX, PauliY, or PauliZ basis in which the message qubit should be prepared\n",
    "3. A Bool indicating the eigenstate in which the message qubit should be prepared\n",
    "\n",
    "**Output:** \n",
    "\n",
    "Two classical bits Alice will send to Bob via classical channel as a tuple of Bool values.  The first bit in the tuple should hold the result of measurement of the message qubit, the second bit - the result of measurement of Alice's qubit.  Represent measurement result 'One' as `true` and 'Zero' as `false`. The state of the qubit qAlice in the end of the operation doesn't matter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T15_PrepareAndSendMessage_Test\n",
    "\n",
    "operation PrepareAndSendMessage (qAlice : Qubit, basis : Pauli, state : Bool) : (Bool, Bool) {\n",
    "    // ...\n",
    "    return (false, false);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 1.6. Reconstruct and measure the message state (Bob's task)\n",
    "\n",
    "Transform Bob's qubit into the required state using the two classical bits received from Alice and measure it in the same basis in which she prepared the message.\n",
    "    \n",
    "**Inputs:**\n",
    "\n",
    "1. Bob's part of the entangled pair of qubits qBob.\n",
    "2. The tuple of classical bits received from Alice, in the format used in task 1.5.\n",
    "3. The PauliX, PauliY, or PauliZ basis in which the message qubit was originally prepared.\n",
    "\n",
    "**Output:** A Bool indicating the eigenstate in which the message qubit was prepared, 'One' as `true` and 'Zero' as `false`.  The state of the qubit qBob in the end of the operation doesn't matter.\n",
    "\n",
    "> To get the output, transform Bob's qubit qBob into the state in which the message qubit was originally prepared, then measure it. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T16_ReconstructAndMeasureMessage_Test\n",
    "\n",
    "operation ReconstructAndMeasureMessage (qBob : Qubit, (b1 : Bool, b2 : Bool), basis : Pauli) : Bool {\n",
    "        \n",
    "    // ...\n",
    "    return false;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 1.7. Testing standard quantum teleportation\n",
    "\n",
    "**Goal:** Test that the `StandardTeleport` operation from task 1.4 is able to successfully teleport the states $|0\\rangle$ and $|1\\rangle$, as well as superposition states such as $\\frac{1}{\\sqrt{2}} \\big(|0\\rangle + |1\\rangle\\big)$, $\\frac{1}{\\sqrt{2}} \\big(|0\\rangle - |1\\rangle\\big)$, $\\frac{1}{\\sqrt{2}} \\big(|0\\rangle + i|1\\rangle\\big)$ and $\\frac{1}{\\sqrt{2}} \\big(|0\\rangle - i|1\\rangle\\big)$.\n",
    "\n",
    "> This is an open-ended task, and is not covered by a unit test. To run the code, execute the cell with the definition of the `Run_StandardTeleport` operation first; if it compiled successfully without any errors, you can run the operation by executing the next cell (`%simulate Run_StandardTeleport`).\n",
    "\n",
    "> Note that this task relies on your implementations of the previous tasks. If you are getting the \"No variable with that name exists.\" error, you might have to execute previous code cells before retrying this task.\n",
    "\n",
    "<details>\n",
    "  <summary>Need a hint? Click here</summary>\n",
    "  You may find your answers for 1.5 and 1.6 useful\n",
    "</details>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "open Microsoft.Quantum.Diagnostics;\n",
    "\n",
    "operation Run_StandardTeleport () : String {\n",
    "    // ...\n",
    "    return \"Success!\";\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%simulate Run_StandardTeleport"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Part II. Teleportation using different entangled pair\n",
    "\n",
    "In this section we will take a look at the changes in the reconstruction process (Bob's task) if the qubits shared between Alice and Bob are entangled in a different state.  Alice's part of the protocol remains the same in all tasks.  \n",
    "As a reminder, the standard teleportation protocol requires shared qubits in state $|\\Phi^{+}\\rangle = \\frac{1}{\\sqrt{2}} \\big(|00\\rangle + |11\\rangle\\big)$.\n",
    "\n",
    "In each task, the inputs are\n",
    "1. Bob's part of the entangled pair of qubits qBob.\n",
    "2. The tuple of classical bits received from Alice, in the format used in task 1.2.\n",
    "\n",
    "The goal is to transform Bob's qubit qBob into the state in which the message qubit had been originally."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 2.1. Reconstruct the message if the entangled qubits were in the state $|\\Phi^{-}\\rangle = \\frac{1}{\\sqrt{2}} \\big(|00\\rangle - |11\\rangle\\big)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T21_ReconstructMessage_PhiMinus_Test\n",
    "\n",
    "operation ReconstructMessage_PhiMinus (qBob : Qubit, (b1 : Bool, b2 : Bool)) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 2.2. Reconstruct the message if the entangled qubits were in the state $|\\Psi^{+}\\rangle = \\frac{1}{\\sqrt{2}} \\big(|01\\rangle + |10\\rangle\\big)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T22_ReconstructMessage_PsiPlus_Test\n",
    "\n",
    "operation ReconstructMessage_PsiPlus (qBob : Qubit, (b1 : Bool, b2 : Bool)) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 2.3. Reconstruct the message if the entangled qubits were in the state $|\\Psi^{-}\\rangle = \\frac{1}{\\sqrt{2}} \\big(|01\\rangle - |10\\rangle\\big)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T23_ReconstructMessage_PsiMinus_Test\n",
    "\n",
    "operation ReconstructMessage_PsiMinus (qBob : Qubit, (b1 : Bool, b2 : Bool)) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Part III. Principle of deferred measurement\n",
    "\n",
    "The principle of deferred measurement claims that measurements can be moved from an intermediate stage of a quantum circuit to the end of the circuit.  If the measurement results are used to perform classically controlled operations, they can be replaced by controlled quantum operations."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 3.1. Measurement-free teleportation.\n",
    "\n",
    "In this task we will apply this principle to the teleportation circuit.\n",
    "\n",
    "**Inputs:** \n",
    "\n",
    "1. The two qubits qAlice and qBob in $|\\Phi^{+}\\rangle$ state.\n",
    "2. The message qubit qMessage in the state $|\\psi\\rangle$ to be teleported.\n",
    "\n",
    "**Goal:** transform Bob's qubit qBob into the state $|\\psi\\rangle$ using no measurements.  At the end of the operation qubits qAlice and qMessage should not be entangled with qBob."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T31_MeasurementFreeTeleport_Test\n",
    "\n",
    "operation MeasurementFreeTeleport (qAlice : Qubit, qBob : Qubit, qMessage : Qubit) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Part IV. Teleportation with three entangled qubits\n",
    "\n",
    "Quantum teleportation using entangled states other than Bell pairs is also feasible.  Here we look at just one of many possible schemes - in it a state is transferred from Alice to a third participant Charlie, but this may only be accomplished if Charlie\n",
    "has the trust of the second participant Bob."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 4.1. Entangled trio\n",
    "\n",
    "**Inputs:** three qubits qAlice, qBob, and qCharlie, each in $|10\\rangle$ state.\n",
    "\n",
    "**Goal:** create an entangled state $|\\Psi^{3}\\rangle = \\frac{1}{2} \\big(|000\\rangle + |011\\rangle + |101\\rangle + |110\\rangle\\big)$ on these qubits.\n",
    "\n",
    "In the context of the quantum teleportation protocol, this is the preparation step: qubits qAlice, qBob, and qCharlie will be sent to Alice, Bob, and Charlie respectively."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T41_EntangleThreeQubits_Test\n",
    "\n",
    "operation EntangleThreeQubits (qAlice : Qubit, qBob : Qubit, qCharlie : Qubit) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 4.2. Reconstruct the message (Charlie's task)\n",
    "\n",
    "Alice has a message qubit in the state $|\\psi\\rangle$  to be teleported, she has entangled it with her own qubit from $|\\Psi^{3}\\rangle$ in the same manner as task 1.2 and extracted two classical bits in order to send them to Charlie. Bob has also measured his own qubit from $|\\Psi^{3}\\rangle$ and sent Charlie the result. Transform Charlie's qubit into the required state using the two classical bits received from Alice, and the one classical bit received from Bob.\n",
    "\n",
    "**Inputs:** \n",
    "1. Charlie's part of the entangled trio of qubits qCharlie.\n",
    "2. The tuple of classical bits received from Alice, in the format used in task 1.2.\n",
    "3. A classical bit resulting from the measurement of Bob's qubit.\n",
    "\n",
    "**Goal:** Transform Charlie's qubit qCharlie into the state in which the message qubit had been originally."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T42_ReconstructMessageWhenThreeEntangledQubits_Test\n",
    "\n",
    "operation ReconstructMessageWhenThreeEntangledQubits (qCharlie : Qubit, (b1 : Bool, b2 : Bool), b3 : Bool) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Q#",
   "language": "qsharp",
   "name": "iqsharp"
  },
  "language_info": {
   "file_extension": ".qs",
   "mimetype": "text/x-qsharp",
   "name": "qsharp",
   "version": "0.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
